home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Games: Greatest Hits 1996
/
Amiga Games: Greatest Hits 1996.iso
/
archive
/
userbox
/
publicdomain
/
fractal.lha
/
fractal
/
source_amiga
/
dec.c
next >
Wrap
C/C++ Source or Header
|
1996-07-02
|
22KB
|
584 lines
/**************************************************************************/
/* Decode an image encoded with a quadtree partition based fractal scheme */
/* */
/* Copyright 1993,1994 Yuval Fisher. All rights reserved. */
/* */
/* Version 0.05 10/10/94 */
/**************************************************************************/
/* see CHANGES.AMIGA for which changes done for the Amiga port
by Andreas R. Kleinert
V1.0: 02-July-96
*/
/* The following belong in a encdec.h file, but nevermind... */
/* -----------------------------------------------------------------------*/
#include <stdio.h>
#include <math.h>
/* added by ak */
#include <string.h>
#include <stdlib.h>
#include <m68881.h>
/* eo - added by ak */
#define DEBUG 0
#define GREY_LEVELS 255
#define IMAGE_TYPE unsigned char /* may be different in some applications */
/* The following #define allocates an hsize x vsize matrix of type type */
#define matrix_allocate(matrix, hsize,vsize, TYPE) {\
TYPE *imptr; \
int _i; \
matrix = (TYPE **)malloc(vsize*sizeof(TYPE *));\
imptr = (TYPE*)malloc((long)hsize*(long)vsize*sizeof(TYPE));\
if (imptr == NULL) \
fatal("\nNo memory in matrix allocate."); \
for (_i = 0; _i<vsize; ++_i, imptr += hsize) \
matrix[_i] = imptr; \
}
#define bound(a) ((a) < 0.0 ? 0 : ((a)>255.0? 255 : a))
#ifdef EXCLUDED_AK
/* various function declarations to keep compiler warnings away */
void fatal();
char *malloc();
char *strcpy();
#endif /* EXCLUDED_AK */
/* ---------------------------------------------------------------------- */
IMAGE_TYPE **image,*imptr,**image1;
/* The input image data and a dummy */
double max_scale = 1.0; /* maximum allowable grey level scale factor */
int s_bits = 5, /* number of bits used to store scale factor */
o_bits = 7, /* number of bits used to store offset */
hsize = -1, /* The horizontal size of the input image */
vsize = -1, /* The vertical size */
scaledhsize, /* hsize*scalefactor */
scaledvsize, /* vsize*scalefactor */
size, /* largest square image that fits in image */
min_part = 3, /* min and max _part determine a range of */
max_part = 4, /* Range sizes from hsize>>min to hsize>>max */
dom_step = 4, /* Density of domains relative to size */
dom_step_type = 0, /* Flag for dom_step a multiplier or divisor */
dom_type = 0, /* Method of generating domain pool 0,1,2.. */
post_process = 1, /* Flag for postprocessing. */
num_iterations= 10, /* Number of decoding iterations used. */
*no_h_domains, /* Number of horizontal domains. */
*domain_hstep, /* Domain density step size. */
*domain_vstep, /* Domain density step size. */
*bits_needed, /* Number of bits to encode domain position. */
zero_ialpha, /* the const ialpha when alpha = 0 */
output_partition=0, /* A flag for outputing the partition */
max_exponent; /* The max power of 2 side of square image */
/* that fits in our input image. */
struct transformation_node {
int rx,ry, /* The range position and size in a trans. */
xsize, ysize,
rrx,rry,
dx,dy; /* The domain position. */
int sym_op; /* The symmetry operation used in the trans. */
int depth; /* The depth in the quadtree partition. */
double scale, offset; /* scalling and offset values. */
struct transformation_node *next; /* The next trans. in list */
} transformations, *trans;
FILE *input,*output,*other_input;
/* fatal is for when there is a fatal error... print a message and exit */
void fatal(s)
char *s;
{
printf("\n%s\n",s);
exit(-1);
}
/* ************************************************************ */
/* unpack value using size bits read from fin. */
/* ************************************************************ */
long unpack(size, fin)
int size;
FILE *fin;
{
int i;
int value = 0;
static int ptr = 1; /* how many bits are packed in sum so far */
static int sum;
/* size == -2 means we initialize things */
if (size == -2) {
sum = fgetc(fin);
sum <<= 1;
return((long)0);
}
/* size == -1 means we want to peek at the next bit without */
/* advancing the pointer */
if (size == -1)
return((long)((sum&256)>>8));
for (i=0; i<size; ++i, ++ptr, sum <<= 1) {
if (sum & 256) value |= 1<<i;
if (ptr == 8) {
sum = getc(fin);
ptr=0;
}
}
return((long)value);
}
main(argc,argv)
int argc;
char **argv;
{
/* Defaults are set initially */
double scalefactor = 1.0; /* Scale factor for output */
char inputfilename[200];
char outputfilename[200];
char other_input_file[200];
int i,j, x_exponent, y_exponent;
int domain_size, no_domains;
inputfilename[0] = 1; /* We initially set the input to this and */
outputfilename[0] = 1; /* then check if the input/output names */
other_input_file[0] = 1; /* have been set below. */
/* scan through the input line and read in the arguments */
for (i=1; i<argc; ++i)
if (argv[i][0] != '-' )
if (inputfilename[0] == 1)
strcpy(inputfilename, argv[i]);
else if (outputfilename[0] == 1)
strcpy(outputfilename, argv[i]);
else;
else { /* we have a flag */
if (strlen(argv[i]) == 1) break;
switch(argv[i][1]) {
case 'i': strcpy(other_input_file,argv[++i]);
break;
case 'n': num_iterations = atoi(argv[++i]);
break;
case 'f': scalefactor = atof(argv[++i]);
break;
case 'P': output_partition = 1;
break;
case 'p': post_process = 0;
break;
case 's': s_bits = atoi(argv[++i]);
break;
case 'o': o_bits = atoi(argv[++i]);
break;
case 'N': max_scale = atof(argv[++i]);
break;
case '?':
case 'H':
default:
printf("\nUsage: dec -[options] [inputfile [outputfile]]");
printf("\nOptions are: (# = number), defaults show in ()");
printf("\n -f # scale factor of output size. (%lf)", scalefactor);
printf("\n -i file name. An initial image to iteration from.");
printf("\n -n # no. of decoding iterations. (%d)", num_iterations);
printf("\n -N # maximum allowed scaling. (%lf)",max_scale);
printf("\n -s # number of scaling quantizing bits. (%d)",s_bits);
printf("\n -o # number of offset quantizing bits. (%d)",o_bits);
printf("\n -P output the partition into the output file. (off)");
printf("\n -p supress artifact postprocessing. (off)");
fatal(" ");
}
}
if (inputfilename[0] == 1) strcpy(inputfilename, "lenna.trn");
if (outputfilename[0] == 1) strcpy(outputfilename, "lenna.out");
if ((input = fopen(inputfilename, "r")) == NULL)
fatal("Can't open input file.");
unpack(-2,input); /* initialize the unpacking routine */
/* read the header data from the input file. This should probably */
/* be put into one read which reads a structure with the info */
min_part = (int)unpack(4,input);
max_part = (int)unpack(4,input);
dom_step = (int)unpack(4,input);
dom_step_type = (int)unpack(1,input);
dom_type = (int)unpack(2,input);
hsize = (int)unpack(12,input);
vsize = (int)unpack(12,input);
/* we now compute size */
x_exponent = (int)floor(log((double)hsize)/log(2.0));
y_exponent = (int)floor(log((double)vsize)/log(2.0));
/* exponent is min of x_ and y_ exponent */
max_exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
/* size is the size of the largest square that fits in the image */
/* It is used to compute the domain and range sizes. */
size = 1<<max_exponent;
/* This is the quantized value of zero scaling */
zero_ialpha = 0.5 + (max_scale)/(2.0*max_scale)*(1<<s_bits);
/* allocate memory for the output image. Allocating one chunck saves */
/* work and time later. */
scaledhsize = (int)(scalefactor*hsize);
scaledvsize = (int)(scalefactor*vsize);
matrix_allocate(image, scaledhsize,scaledvsize, IMAGE_TYPE);
matrix_allocate(image1, scaledhsize, scaledvsize, IMAGE_TYPE);
if (other_input_file[0] != 1) {
other_input = fopen(other_input_file, "r");
i = fread(image[0], sizeof(IMAGE_TYPE),
scaledhsize*scaledvsize, other_input);
if (i < scaledhsize*scaledvsize)
fatal("Couldn't read input... not enough data.");
else
printf("\n%d pixels read from %s.\n", i,other_input_file);
fclose(other_input);
}
/* since max_ and min_ part are variable, these must be allocated */
i = max_part - min_part + 1;
bits_needed = (int *)malloc(sizeof(int)*i);
no_h_domains = (int *)malloc(sizeof(int)*i);
domain_hstep = (int *)malloc(sizeof(int)*i);
domain_vstep = (int *)malloc(sizeof(int)*i);
/* compute bits needed to read each domain type */
for (i=0; i <= max_part-min_part; ++i) {
/* first compute how many domains there are horizontally */
domain_size = size >> (min_part+i-1);
if (dom_type == 2)
domain_hstep[i] = dom_step;
else if (dom_type == 1)
if (dom_step_type ==1)
domain_hstep[i] = (size >> (max_part - i-1))*dom_step;
else
domain_hstep[i] = (size >> (max_part - i-1))/dom_step;
else
if (dom_step_type ==1)
domain_hstep[i] = domain_size*dom_step;
else
domain_hstep[i] = domain_size/dom_step;
no_h_domains[i] = 1+(hsize-domain_size)/domain_hstep[i];
/* bits_needed[i][0] = ceil(log(no_domains)/log(2)); */
/* now compute how many domains there are vertically */
if (dom_type == 2)
domain_vstep[i] = dom_step;
else if (dom_type == 1)
if (dom_step_type ==1)
domain_vstep[i] = (size >> (max_part - i-1))*dom_step;
else
domain_vstep[i] = (size >> (max_part - i-1))/dom_step;
else
if (dom_step_type ==1)
domain_vstep[i] = domain_size*dom_step;
else
domain_vstep[i] = domain_size/dom_step;
no_domains = 1+(vsize-domain_size)/domain_vstep[i];
bits_needed[i] = ceil(log((double)no_domains*(double)no_h_domains[i])/
log(2.0));
}
if ((output = fopen(outputfilename, "w")) == NULL)
fatal("Can't open output file.");
/* Read in the transformation data */
trans = &transformations;
printf("\nReading transformations.....");
fflush(stdout);
partition_image(0, 0, hsize,vsize );
fclose(input);
printf("Done.");
fflush(stdout);
if (scalefactor != 1.0) {
printf("\nScaling image to %d x %d.", scaledhsize,scaledvsize);
scale_transformations(scalefactor);
}
/* when we output the partition, we just read the transformations */
/* in and write them to the outputfile */
if (output_partition) {
fprintf(output,"\n%d %d\n %d %d\n%d %d\n\n",
0, 0, scaledhsize, 0, scaledhsize, scaledvsize);
printf("\nOutputed partition data in %s\n",outputfilename);
fclose(output);
return;
}
for (i=0; i<num_iterations; ++i)
apply_transformations();
if (post_process)
smooth_image();
i = fwrite(image[0], sizeof(IMAGE_TYPE), scaledhsize*scaledvsize, output);
if (i < scaledhsize*scaledvsize)
fatal("Couldn't write output... not enough disk space ?.");
else
printf("\n%d pixels written to output file.\n", i);
fclose(output);
}
/* ************************************************************ */
/* Read in the transformation data from *input. */
/* This is a recursive routine whose recursion tree follows the */
/* recursion done by the encoding program. */
/* ************************************************************ */
read_transformations(atx,aty,xsize,ysize,depth)
int atx,aty,xsize,ysize,depth;
{
/* Having all these locals in a recursive procedure is hard on the */
/* stack.. but it is more readable. */
int i,j,
sym_op, /* A symmetry operation of the square */
ialpha, /* Intgerized scalling factor */
ibeta; /* Intgerized offset */
long domain_ref;
double alpha, beta;
/* keep breaking it down until we are small enough */
if (depth < min_part) {
read_transformations(atx,aty, xsize/2, ysize/2, depth+1);
read_transformations(atx+xsize/2,aty, xsize/2, ysize/2, depth+1);
read_transformations(atx,aty+ysize/2,xsize/2, ysize/2, depth+1);
read_transformations(atx+xsize/2,aty+ysize/2,xsize/2,ysize/2,depth+1);
return;
}
if (depth < max_part && unpack(1,input)) {
/* A 1 means we subdivided.. so quadtree */
read_transformations(atx,aty, xsize/2, ysize/2, depth+1);
read_transformations(atx+xsize/2,aty, xsize/2, ysize/2, depth+1);
read_transformations(atx,aty+ysize/2, xsize/2, ysize/2, depth+1);
read_transformations(atx+xsize/2,aty+ysize/2,xsize/2,ysize/2,depth+1);
} else {
/* we have a transformation to read */
trans->next = (struct transformation_node *)
malloc(sizeof(struct transformation_node ));
trans = trans->next; trans->next = NULL;
ialpha = (int)unpack(s_bits, input);
ibeta = (int)unpack(o_bits, input);
alpha = (double)ialpha/(double)(1<<s_bits)*(2.0*max_scale)-max_scale;
beta = (double)ibeta/(double)((1<<o_bits)-1)*
((1.0+fabs(alpha))*GREY_LEVELS);
if (alpha > 0.0) beta -= alpha*GREY_LEVELS;
trans->scale = alpha;
trans->offset = beta;
if (ialpha != zero_ialpha) {
trans-> sym_op = (int)unpack(3, input);
domain_ref = unpack(bits_needed[depth-min_part], input);
trans->dx = (double)(domain_ref % no_h_domains[depth-min_part])
* domain_hstep[depth-min_part];
trans->dy = (double)(domain_ref / no_h_domains[depth-min_part])
* domain_vstep[depth-min_part];
} else {
trans-> sym_op = 0;
trans-> dx = 0;
trans-> dy = 0;
}
trans->rx = atx;
trans->ry = aty;
trans->depth = depth;
trans->rrx = atx + xsize;
trans->rry = aty + ysize;
if (output_partition)
fprintf(output,"\n%d %d\n %d %d\n%d %d\n\n",
atx, vsize-aty-ysize,
atx, vsize-aty,
atx+xsize, vsize-aty);
}
}
/* ************************************************************ */
/* Apply the transformations once to an initially black image. */
/* ************************************************************ */
apply_transformations()
{
IMAGE_TYPE **tempimage;
int i,j,i1,j1,count=0;
double pixel;
trans = &transformations;
while (trans->next != NULL) {
trans = trans->next;
++count;
/* Since the inner loop is the same in each case of the switch below */
/* we just define it once for easy modification. */
#define COMPUTE_LOOP { \
pixel = (image[j1][i1]+image[j1][i1+1]+image[j1+1][i1]+ \
image[j1+1][i1+1])/4.0; \
image1[j][i] = bound(0.5 + trans->scale*pixel+trans->offset);\
}
switch(trans->sym_op) {
case 0: for (i=trans->rx, i1 = trans->dx;
i<trans->rrx; ++i, i1 += 2)
for (j=trans->ry, j1 = trans->dy;
j<trans->rry; ++j, j1 += 2)
COMPUTE_LOOP
break;
case 1: for (j=trans->ry, i1 = trans->dx;
j<trans->rry; ++j, i1 += 2)
for (i=trans->rrx-1,
j1 = trans->dy; i>=(int)trans->rx; --i, j1 += 2)
COMPUTE_LOOP
break;
case 2: for (i=trans->rrx-1,
i1 = trans->dx; i>=(int)trans->rx; --i, i1 += 2)
for (j=trans->rry-1,
j1 = trans->dy; j>=(int)trans->ry; --j, j1 += 2)
COMPUTE_LOOP
break;
case 3: for (j=trans->rry-1,
i1 = trans->dx; j>=(int)trans->ry; --j, i1 += 2)
for (i=trans->rx, j1 = trans->dy;
i<trans->rrx; ++i, j1 += 2)
COMPUTE_LOOP
break;
case 4: for (j=trans->ry, i1 = trans->dx;
j<trans->rry; ++j, i1 += 2)
for (i=trans->rx, j1 = trans->dy;
i<trans->rrx; ++i, j1 += 2)
COMPUTE_LOOP
break;
case 5: for (i=trans->rx, i1 = trans->dx;
i<trans->rrx; ++i, i1 += 2)
for (j=trans->rry-1,
j1 = trans->dy; j>=(int)trans->ry; --j, j1 += 2)
COMPUTE_LOOP
break;
case 6: for (j=trans->rry-1,
i1 = trans->dx; j>=(int)trans->ry; --j, i1 += 2)
for (i=trans->rrx-1,
j1 = trans->dy; i>=(int)trans->rx; --i, j1 += 2)
COMPUTE_LOOP
break;
case 7: for (i=trans->rrx-1,
i1 = trans->dx; i>=(int)trans->rx; --i, i1 += 2)
for (j=trans->ry, j1 = trans->dy;
j<trans->rry; ++j, j1 += 2)
COMPUTE_LOOP
break;
}
}
tempimage = image;
image = image1;
image1 = tempimage;
printf("\n%d transformations applied.",count);
}
/* This should really be done when they are read in. */
/* ************************************************************ */
scale_transformations(scalefactor)
double scalefactor;
{
trans = &transformations;
while (trans->next != NULL) {
trans = trans->next;
trans->rrx *= scalefactor;
trans->rry *= scalefactor;
trans->rx *= scalefactor;
trans->ry *= scalefactor;
trans->dx *= scalefactor;
trans->dy *= scalefactor;
}
}
/* ************************************************************* */
/* Recursively partition an image, finding the largest contained */
/* square and call read_transformations . */
/* ************************************************************* */
partition_image(atx, aty, hsize,vsize )
int atx, aty, hsize,vsize;
{
int x_exponent, /* the largest power of 2 image size that fits */
y_exponent, /* horizontally or vertically the rectangle. */
exponent, /* The actual size of image that's encoded. */
size,
depth;
x_exponent = (int)floor(log((double)hsize)/log(2.0));
y_exponent = (int)floor(log((double)vsize)/log(2.0));
/* exponent is min of x_ and y_ exponent */
exponent = (x_exponent > y_exponent ? y_exponent : x_exponent);
size = 1<<exponent;
depth = max_exponent - exponent;
read_transformations(atx,aty,size,size,depth);
if (size != hsize)
partition_image(atx+size, aty, hsize-size,vsize );
if (size != vsize)
partition_image(atx, aty+size, size,vsize-size );
}
/* ************************************************************* */
/* Scan the image and average the transformation boundaries. */
/* ************************************************************* */
smooth_image()
{
IMAGE_TYPE pixel1, pixel2;
int i,j;
int w1,w2;
printf("\nPostprocessing Image.");
trans = &transformations;
while (trans->next != NULL) {
trans = trans->next;
if (trans->rx == 0 || trans->ry == 0)
continue;
if (trans->depth == max_part) {
w1 = 5;
w2 = 1;
} else {
w1 = 2;
w2 = 1;
}
for (i=trans->rx; i<trans->rrx; ++i) {
pixel1 = image[(int)trans->ry][i];
pixel2 = image[(int)trans->ry-1][i];
image[(int)trans->ry][i] = (w1*pixel1 + w2*pixel2)/(w1+w2);
image[(int)trans->ry-1][i] = (w2*pixel1 + w1*pixel2)/(w1+w2);
}
for (j=trans->ry; j<trans->rry; ++j) {
pixel1 = image[j][(int)trans->rx];
pixel2 = image[j][(int)trans->rx-1];
image[j][(int)trans->rx] = (w1*pixel1 + w2*pixel2)/(w1+w2);
image[j][(int)trans->rx-1] = (w2*pixel1 + w1*pixel2)/(w1+w2);
}
}
}